/**
 * Class Philosopher.
 * Outlines main subrutines of our virtual philosopher. 
 *
 * @author Serguei A. Mokhov, mokhov@cs.concordia.ca
 */
public class Philosopher extends Thread
{
	/**
	 * Max time an action can take (in milliseconds)
	 */
	public static final long TIME_TO_WASTE = 1000;

	public static int topTID = 0; // keeps track of highest TID. ALSO it will be the next TID assigned. 
	int TID;  // philosophers TID
	
	/**
	 * constructor which sets TID
	 */
	public Philosopher()
	{
		System.out.println("Philosopher.Phil()");
		int TID = topTID; // sets TID of the newly created instance of philosopher 
		topTID +=1;		// increments the topTID by 1 and it will be used as the next TID. 
	}
	
	
	private int getTID()
	{
		System.out.println("Philosopher.getTID()");
		return TID;
	}
	
	/**
	 * The act of eating.
	 * - Print the fact that a given phil (their TID) has started eating.
	 * - Then sleep() for a random interval.
	 * - The print that they are done eating.
	 */
	public synchronized  void eat()
	{
		
		System.out.println("philosopher #" + getTID() + "is eating"); 
		
		long startTime =  System.currentTimeMillis();
	    while (System.currentTimeMillis()- startTime < TIME_TO_WASTE){}			// loop (eat) for 1000 milliseconds
	    
		try
		{
			sleep((long)(Math.random() * TIME_TO_WASTE));
		}
		catch(InterruptedException e)
		{
			System.err.println("Philosopher.eat():");
			DiningPhilosophers.reportException(e);
			System.exit(1);
		}
		
		System.out.println("philosopher #" + getTID() + "is DONE eating"); 
	}

	/**
	 * The act of thinking.
	 * - Print the fact that a given phil (their TID) has started thinking.
	 * - Then sleep() for a random interval.
	 * - The print that they are done thinking.
	 */
	public synchronized  void think()
	{
		System.out.println("philosopher #" + getTID() + "is thinking");
		long startTime =  System.currentTimeMillis();
	    while ( System.currentTimeMillis() - startTime < TIME_TO_WASTE){}				// loop (think) for 1000 milliseconds
		System.out.println("philosopher #" + getTID() + "is DONE thinking");
	}

	/**
	 * The act of talking.
	 * - Print the fact that a given phil (their TID) has started talking.
	 * - Say something brilliant at random
	 * - The print that they are done talking.
	 */
	public synchronized void talk()
	{
		System.out.println("philosopher #" + getTID() + "is talking");

		saySomething();
		long startTime =  System.currentTimeMillis();
	    while ( System.currentTimeMillis() - startTime < TIME_TO_WASTE){}				// loop (talk) for 1000 milliseconds

		System.out.println("philosopher #" + getTID() + "is DONE talking");
	}

	/**
	 * No, this is not the act of running, just the overridden Thread.run()
	 */
	public synchronized  void run()
	{
		for(int i = 0; i < DiningPhilosophers.DINING_STEPS; i++)
		{
			DiningPhilosophers.soMonitor.pickUp(getTID());

			eat();

			DiningPhilosophers.soMonitor.putDown(getTID());

			think();

			/*
			 * TODO:
			 * A decision is made at random whether this particular
			 * philosopher is about to say something terribly useful.
			 */
			if(true == false)
			{
				// Some monitor ops down here...
				talk();
				// ...
			}


		}
	} // run()

	/**
	 * Prints out a phrase from the array of phrases at random.
	 * Feel free to add your own phrases.
	 */
	public void saySomething()
	{
		System.out.println("...saySomething() called...");
		String[] astrPhrases =
		{
			"Eh, it's not easy to be a philosopher: eat, think, talk, eat...",
			"You know, true is false and false is true if you think of it",
			"2 + 2 = 5 for extremely large values of 2...",
			"If thee cannot speak, thee must be silent",
			"My number is " + getTID() + ""
		};

		System.out.println
		(
			"Philosopher " + getTID() + " says: " +
			astrPhrases[(int)(Math.random() * astrPhrases.length)]
		);
	}
}

// EOF
